﻿using DnD.Common;
using DnD.Model;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Tasks;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Windows.Storage;

namespace DnD.ViewModels
{
    class CardViewModel : INotifyPropertyChanged
    {
        private PhoneApplicationPage _view;
        private Card _selectedCard;
        private DnDRestService restService;
        private string _picturePath;
        public ObservableCollection<DnDAction> Actions { get; set; }

        private String[] persitentProperties = new String[] { "cardEditorName", "cardEditorDesc", "cardEditorPicsURL", "cardEditorPicModified", "cardEditorLocalPicName"};

        public DelegateCommand SelectPictureCommand { get; set; }

        public Card SelectedCard
        {
            get { return _selectedCard; }
            set
            {
                _selectedCard = value;
                OnPropertyChanged();
                
            }
        }

        public string PicturePath
        {
            get { return _picturePath; }
            set
            {
                _picturePath = value;
                OnPropertyChanged();

            }
        }


        public CardViewModel(int cardID, PhoneApplicationPage view, bool stateSaveRequired)
        {
            _view = view;

            using (var context = new DnDDataContext(DnDDataContext.DbConnectionString))
            {
                var cards = from c in context.GameItems where c.Id == cardID select c ;
                if (cards.Count() == 0)
                {
                    _view.NavigationService.GoBack();
                    return;
                }
                foreach (Card c in cards)
                {
                    SelectedCard = c;

                    if (SelectedCard.LocalPictureName != null && SelectedCard.LocalPictureName != "")
                    {
                        PicturePath = SelectedCard.LocalPictureName;
                    }
                    else
                    {
                        PicturePath = SelectedCard.PictureURL;
                    }

                    Actions = new ObservableCollection<DnDAction>();

                    foreach(CardAction action in c.Actions)
                    {
                        Actions.Add(action.ActionRef);
                    }

                }
            }
            bool allPropertiesPersisted = true;
            for (int i = 0; i < persitentProperties.Length; i++)
            {
                if (!(App.appStateMap.ContainsKey(persitentProperties[i])) || !( App.appStateMap[persitentProperties[i]] != null))
                {
                    allPropertiesPersisted = false;
                    break;
                }
            }

            if (allPropertiesPersisted)
            {
                SelectedCard.Name = (string)App.appStateMap["cardEditorName"];
                SelectedCard.Description = (string)App.appStateMap["cardEditorDesc"];
                SelectedCard.PictureURL = (string)App.appStateMap["cardEditorPicsURL"];
                SelectedCard.IsPictureModified = (bool)App.appStateMap["cardEditorPicModified"];
                SelectedCard.LocalPictureName = (string)App.appStateMap["cardEditorLocalPicName"];
                PicturePath = (string)App.appStateMap["cardEditorLocalPicName"];
            }



            if (stateSaveRequired)
            {
                SelectedCard.PropertyChanged += SelectedCard_PropertyChanged;
            }
            
            restService = new DnDRestService();

            SelectPictureCommand = new DelegateCommand(selectPicture, name => true);

            

        }

        private void selectPicture(object obj)
        {
            PhotoChooserTask photoChooserTask = new PhotoChooserTask();
            photoChooserTask.Completed += new EventHandler<PhotoResult>(photoChooserTask_Completed);
            photoChooserTask.Show();


        }

        async void photoChooserTask_Completed(object sender, PhotoResult e)
        {
            if (e.TaskResult == TaskResult.OK)
            {








                SelectedCard.IsPictureModified = true;
               


                StorageFile file = await SaveToLocalFolderAsync(e.ChosenPhoto, "picture" + SelectedCard.Id);

                SelectedCard.IsPictureModified = true;
                SelectedCard.LocalPictureName = file.Path;
                PicturePath = file.Path;
            }
        }

        public async Task<StorageFile> SaveToLocalFolderAsync(Stream file, string fileName)
        {
            StorageFolder localFolder = ApplicationData.Current.LocalFolder;
            StorageFile storageFile = await localFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
            using (Stream outputStream = await storageFile.OpenStreamForWriteAsync())
            {
                await file.CopyToAsync(outputStream);
            }

            return storageFile;

        }


        void SelectedCard_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            App.appStateMap["cardEditorName"] = SelectedCard.Name;
            App.appStateMap["cardEditorDesc"] = SelectedCard.Description;
            App.appStateMap["cardEditorPicsURL"] = SelectedCard.PictureURL;
            App.appStateMap["cardEditorPicModified"] = SelectedCard.IsPictureModified;
            App.appStateMap["cardEditorLocalPicName"] = SelectedCard.LocalPictureName;
            PicturePath = SelectedCard.LocalPictureName;

        }

        public async void handleMenuRequest(String menuItemName)
        {
            if (menuItemName == "save")
            {
                using (var context = new DnDDataContext(DnDDataContext.DbConnectionString))
                {
                    var cards = from c in context.GameItems where c.Id == SelectedCard.Id select c;
                    foreach (Card c in cards)
                    {
                        c.Description = SelectedCard.Description;
                        c.Name = SelectedCard.Name;
                        c.PictureURL = SelectedCard.PictureURL;
                        c.Local = true;
                        SelectedCard.Local = true;
                        context.SubmitChanges();
                    }
                    MessageBox.Show("Card is saved!");
                 
                }
            }
            else if (menuItemName == "delete")
            {
                using (var context = new DnDDataContext(DnDDataContext.DbConnectionString))
                {
                    var cards = from c in context.GameItems where c.Id == SelectedCard.Id select c;
                    foreach (Card c in cards)
                    {
                        context.GameItems.DeleteOnSubmit(c);
                    }
                    context.SubmitChanges();
                    if (SelectedCard.OnlineID != 0)
                    {
                        if (MessageBox.Show("Do you want to delete the card also from the server?", "Delete Card", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                        {
                            restService.deleteCard(SelectedCard.OnlineID,UserViewModel.userName, UserViewModel.sessionID, restDeleteResultHandler);
                        }
                    }
                }
            }
            else if (menuItemName == "upload")
            {
                if (SelectedCard.OnlineID != 0 && SelectedCard.Local)
                {

                    restService.updateCard(SelectedCard.OnlineID, SelectedCard.Name, SelectedCard.Description, UserViewModel.userName, UserViewModel.sessionID, restUpdateResultHandler);

                    SelectedCard.Local = false;

                    if (SelectedCard.IsPictureModified)
                    {
                        StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
                        StorageFile picture = await storageFolder.GetFileAsync(SelectedCard.LocalPictureName);

                        Stream pictureStream = await picture.OpenStreamForReadAsync();

                        HttpResponseMessage response =  await restService.UploadImage(MapViewModel.ReadToEnd(pictureStream),SelectedCard.OnlineID, UserViewModel.userName, UserViewModel.sessionID);

                        SelectedCard.IsPictureModified = false;
                    }

                }
                else
                {
                    MessageBox.Show("Card cannot be uploaded!");

                }
            }
        }

        private string restDeleteResultHandler(bool result)
        {
            if (result)
            {
                MessageBox.Show("Card deleted from server!");
                return "OK";
            }
            else
            {
                MessageBox.Show("Problem occured while deleting card from server!");
                return "ERROR";
            }

            
        }

        private string restUpdateResultHandler(bool result)
        {
            if (result)
            {
                MessageBox.Show("Card uploaded to the server!");
                return "OK";
            }
            else
            {
                MessageBox.Show("Problem occured while uploading card to server!");
                return "ERROR";
            }


        }

        public void editCard()
        {
            if (UserViewModel.checkIfUserLoggedIn() && SelectedCard.Author == UserViewModel.userName)
            {
                _view.NavigationService.Navigate(new Uri("/CardEditorPage.xaml?cardID=" + SelectedCard.Id, UriKind.Relative));
            }
            else
            {
                MessageBox.Show("You can not edit this card!");
            }


        }

        public void clearAppState()
        {
            App.appStateMap["cardEditorName"] = null;
            App.appStateMap["cardEditorDesc"] = null;
            App.appStateMap["cardEditorPicsURL"] = null;
        }


        public string BackGroundImageSource
        {
            get
            {
                if ((Visibility)App.Current.Resources["PhoneDarkThemeVisibility"]
                  == Visibility.Visible)
                {
                    return "/Assets/Pictures/fire3.jpg";

                }
                else
                {
                    return "/Assets/Pictures/fire3_negative.jpg";

                }
            }
            private set { }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }


    }
}
